package com.northking.statisticsdemo.circleQueue;

import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.lmax.disruptor.RingBuffer;
import com.northking.chainResponsibility.ChainEntityAnnotation;
import com.northking.chainResponsibility.ChainEntityInterface;
import com.northking.chainResponsibility.ChainEntryInterface;
import org.reflections.Reflections;
import org.reflections.util.ConfigurationBuilder;
import org.springframework.stereotype.Component;

import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author BigHead
 * @date 2021/11/1 10:54
 * @description CircleQueueProducer
 */
@Component
public class CircleQueueProducer extends DynamicLoadBusinessJar {

    private static final String ENTITY_NAME_KEY = "entityName";
    private static final String ENTITY_VALUE_KEY = "entityValue";

    private final Map<String, Class<? extends ChainEntityInterface>> chainEntityInterfaceMap;
    private final Map<String, String> chainEntryMap;

    private final RingBuffer<CircleQueueEvent> circleQueueEventRingBuffer;

    public CircleQueueProducer(CircleQueueInit circleQueueInit) {
        this.circleQueueEventRingBuffer = circleQueueInit.getCircleQueueEventDisruptor().getRingBuffer();
        chainEntityInterfaceMap = new ConcurrentHashMap<>();
        chainEntryMap = new ConcurrentHashMap<>();
        flushChainEntity();
    }

    public void productionEvent(JSONObject entityJson) {
        ChainEntityInterface chainEntityInterface = makeChainEntityInterface(entityJson);
        if (null == chainEntityInterface) {
            // 这里应该打印log日志
            System.out.println("没有对应实体");
            return;
        }
        long queue = circleQueueEventRingBuffer.next();
        try {
            circleQueueEventRingBuffer.get(queue).setChainEntryName(chainEntryMap.get(entityJson.getString(ENTITY_NAME_KEY)));
            circleQueueEventRingBuffer.get(queue).setChainEntityInterface(chainEntityInterface);
        } finally {
            circleQueueEventRingBuffer.publish(queue);
        }
    }

    private ChainEntityInterface makeChainEntityInterface(JSONObject entityJson) {
        ChainEntityInterface chainEntityInterface = null;
        String entityName = entityJson.getString(ENTITY_NAME_KEY);
        if (chainEntityInterfaceMap.containsKey(entityName)) {
            Class<? extends ChainEntityInterface> chainEntityInterfaceClass = chainEntityInterfaceMap.get(entityName);
            chainEntityInterface = JSON.parseObject(entityJson.getString(ENTITY_VALUE_KEY), chainEntityInterfaceClass);
        }
        return chainEntityInterface;
    }

    /**
     * 动态扫描装载 责任链业务对象
     */
    public void flushChainEntity() {
        initJarPath();
        Set<Class<?>> chainEntityClassSet = reflections.getTypesAnnotatedWith(ChainEntityAnnotation.class);
        Map<String, Class<? extends ChainEntityInterface>> chainEntityInterfaceTempMap = new HashMap<>(chainEntityClassSet.size());
        for (Class<?> clazz : chainEntityClassSet) {
            final ChainEntityAnnotation chainEntityAnnotation = clazz.getAnnotation(ChainEntityAnnotation.class);
            Class<? extends ChainEntryInterface> chainEntryInterfaceClass = chainEntityAnnotation.chainEntryClass();
            Class<? extends ChainEntityInterface> chainEntityInterfaceClass = chainEntityAnnotation.chainEntityClass();

            chainEntityInterfaceTempMap.put(
                    chainEntityInterfaceClass.getSimpleName(),
                    chainEntityInterfaceClass
            );
            chainEntityInterfaceMap.put(
                    chainEntityInterfaceClass.getSimpleName(),
                    chainEntityInterfaceClass
            );
            chainEntryMap.put(
                    chainEntityInterfaceClass.getSimpleName(),
                    chainEntryInterfaceClass.getSimpleName()
            );
        }

        for (String chainEntityName : chainEntityInterfaceMap.keySet()) {
            if (!chainEntityInterfaceTempMap.containsKey(chainEntityName)) {
                chainEntityInterfaceMap.remove(chainEntityName);
                chainEntryMap.remove(chainEntityName);
            }
        }
    }

}
